
#include <assert.h>

#include "OutAndNode.hpp"

OutAndNode::OutAndNode() :
        ExpressionNode(),
        _child(0)
{

}

OutAndNode::~OutAndNode()
{

}

Tribool OutAndNode::solve(Universe &universe)
{
    if (this->_solved)
        return this->_value;
    assert(this->_child != 0);
    Tribool r = this->_child->solve(universe);
    if (r.value == TriboolVal::OutOrStopped)
        this->_value = TriboolVal::OutOrStopped;
    else if (r.value == TriboolVal::True)
        this->_value = TriboolVal::True;
    else if (r.value == TriboolVal::False &&
             (this->_child->getType() == NodeType::OutOr || this->_child->getType() == NodeType::OutAnd))
    {
        std::cout << "should duplicate universe in out and solving" << std::endl;
        this->_value = TriboolVal::False;
    }
    if (r.value == TriboolVal::False)
        std::cout << "false out and" << std::endl;
    this->_solved = true;
    return this->_value;
}

ExpressionNode* OutAndNode::clone(std::map<int, ExpressionNode*>& existingNodes)
{
    if (existingNodes.find(this->_id) != existingNodes.end())
        return existingNodes[this->_id];
    OutAndNode* clone = new OutAndNode();
    clone->_id = this->_id;
    clone->_solved = this->_solved;
    clone->_value = this->_value;
    existingNodes[this->_id] = clone;
    clone->_child = (this->_child != 0) ? this->_child->clone(existingNodes) : 0;
    return clone;
}

void OutAndNode::addChild(ExpressionNode *child)
{
    this->_child = child;
}

NodeType::Type OutAndNode::getType() const
{
    return NodeType::OutAnd;
}
